/**
 * Bij childcoordinates werken met die vectorklasse?
 */


package asteroids.model;

import java.util.Random;

import be.kuleuven.cs.som.annotate.Immutable;

import asteroids.Util;

public class Asteroid extends CollisionObject{

	//VERDER UITWERKEN
	public Asteroid (double xCoordinate, double yCoordinate, double xVelocity, double yVelocity, double radius, Random random){
		super(xCoordinate, yCoordinate, xVelocity, yVelocity, radius);
		randomGenerator = new Random();
	}

	private Random randomGenerator;
	// hier ook een costructor met density? --> in collisionObject zetten?
		public Asteroid (double xCoordinate, double yCoordinate, double xVelocity, double yVelocity, double radius, double density){
		super(xCoordinate, yCoordinate, xVelocity, yVelocity, radius);
		//isValidDensity();
		this.density = density;
	}



	public Asteroid(double xCoordinate, double yCoordinate, double xVelocity,double yVelocity, double radius)//, double angle, double mass)
			throws OutOfBoundsException, IllegalRadiusException {
		super(xCoordinate, yCoordinate, xVelocity, yVelocity, radius);
		setMass(radius);
	}

	
	@Override
	protected double getMinimumMass() {
		return this.minimumMass;
	}
	private final double minimumMass = 0;
	@Override
	protected double getMaximumMass() {
		return this.maximumMass;
	}
private final double maximumMass = Double.POSITIVE_INFINITY;
	@Override
	protected CollisionObject getObjectAtColissionPosition(CollisionObject asteroid, double timeLapse) {
		double newXCoordinate = asteroid.getXVelocity()*timeLapse + asteroid.getXCoordinate();
		double newYCoordinate = asteroid.getYVelocity()*timeLapse + asteroid.getYCoordinate();
		Asteroid resultAsteroid = new Asteroid(newXCoordinate,newYCoordinate,asteroid.getXVelocity(),asteroid.getYVelocity(),asteroid.getRadius());
		return resultAsteroid;
	}
	@Override
	public void setMass(double radius){
		this.mass = Math.pow(radius, 3)*4/3/Math.PI*getDensity();
	}
	private double getDensity(){
		return this.density;
	}
	private double mass;
	private double density = 2.65*Math.pow(10, 12);

	// MSS OVERKOEPELEND DOEN IN COLLISIONOBJ
	//TODO wordt nie gebruikt 
	public World getAsteroidWorld(Asteroid asteroid){
		return asteroid.getWorld();}


	@Override
	public void collisionReactionWith(CollisionObject collisionObject) {
		if(collisionObject.isAsteroid()){
			this.bounceOff();
			collisionObject.bounceOff();
		}
		if(collisionObject.isBullet()){
			collisionObject.destroy();
			this.destroy();
		}
		if(collisionObject.isShip()){
			collisionObject.destroy();
		}
	}


	//TRYEN WANT ALS ER EEN PROBLEEM IS MET DE RAND MOET HIJ BLIJVEN PROBEREN!!
	public void destroy(){
		if(Util.fuzzyEquals(this.getRadius(), getMinimumSizeForSplittin())){
			if(!Util.fuzzyLessThanOrEqualTo(this.getRadius(), 30)) {
				super.destroy();
			}
		}
		else{
			int random = randomGenerator.nextInt(360);
			double angle = Math.toRadians(random);
			double totalVelocity =this.getTotalVelocity(getXVelocity(), getYVelocity());
			double newXVelocity;
			double newYVelocity;
			// OF isValidVelocity(getChildVelocityMultiplicator()*totalVelocity)) // maar als dan op andere manier total velocity berekend wordt.. Kan evt vermeden worden door dit in de documentatie te schrijven.
			if(isValidVelocity(getChildXVelocity(angle, totalVelocity), getChildYVelocity(angle, totalVelocity))){
				newXVelocity = getChildXVelocity(angle, totalVelocity);
				newYVelocity = getChildYVelocity(angle, totalVelocity);
			}
			else{
				newXVelocity = getSpeedOfLight()*Math.cos(angle);
				newYVelocity = getSpeedOfLight()*Math.sin(angle);
																
			}
			Asteroid child1 = new Asteroid(getFirstChildXCoordinate(angle), getFirstChildYCoordinate(angle), newXVelocity, newYVelocity, getChildRadius());
			Asteroid child2 = new Asteroid(getSecondChildXCoordinate(angle), getSecondChildYCoordinate(angle), -newXVelocity, -newYVelocity, getChildRadius());
			child1.setWorld(this.getWorld());
			child2.setWorld(this.getWorld());
			if(child1.exceedsWorldBoundaries() || child2.exceedsWorldBoundaries()){
				child1.completeDestruction();
				child2.completeDestruction();
				destroy();
			}
		}
	}
	//TODO waarom niet gewoon this
	private void completeDestruction(){
		super.destroy();
	}

//	private Asteroid generateChildAsteroid(){
//		double newXVelocity;
//		double newYVelocity;
//		int random = randomGenerator.nextInt(360);
//		double angle = Math.toRadians(random);
//		double totalVelocity =this.getTotalVelocity(this.getXVelocity(), this.getYVelocity());
//		// OF isValidVelocity(getChildVelocityMultiplicator()*totalVelocity)) // maar als dan op andere manier total velocity berekend wordt.. Kan evt vermeden worden door dit in de documentatie te schrijven.
//		if(isValidVelocity(getChildXVelocity(angle, totalVelocity), getChildYVelocity(angle, totalVelocity))){
//			newXVelocity = getChildXVelocity(angle, totalVelocity);
//			newYVelocity = getChildYVelocity(angle, totalVelocity);
//		}
//		else{
//			newXVelocity = getSpeedOfLight()*Math.cos(angle);
//			newYVelocity = getSpeedOfLight()*Math.sin(angle);
//		}
//		Asteroid child = new Asteroid(getFirstChildXCoordinate(angle), getFirstChildYCoordinate(angle), newXVelocity, newYVelocity, getChildRadius());
//		return child;
//	}

	private double getChildRadius(){
		double newRadius = this.getRadius()/2;
		if(this.isValidRadius(newRadius))
			return newRadius;
		throw new IllegalRadiusException("Invalid childradius");
	}

	private double getChildXVelocity(double angle, double totalVelocity){
		return getChildVelocityMultiplicator()*totalVelocity*Math.cos(angle);
	}

	private double getChildYVelocity(double angle, double totalVelocity){
		return getChildVelocityMultiplicator()*totalVelocity*Math.sin(angle);
	}

	private double getFirstChildXCoordinate(double angle){
		return (this.getRadius()/2)*Math.cos(angle)		+this.getXCoordinate();
	}

	private double getFirstChildYCoordinate(double angle){
		return (this.getRadius()/2)*Math.sin(angle)		+this.getYCoordinate()*Math.sin(angle);
	}

	private double getSecondChildXCoordinate(double angle){
		return -((this.getRadius()/2)*Math.cos(angle))	+this.getXCoordinate();
	}

	private double getSecondChildYCoordinate(double angle){
		return	-((this.getRadius()/2)*Math.sin(angle))	+this.getYCoordinate();
	}

	private final double minimumSizeForSplitting = 30;
	private final double childVelocityMultiplicator = 1.5;

	@Immutable
	private double getChildVelocityMultiplicator(){
		return this.childVelocityMultiplicator;
	}

	@Immutable
	private double getMinimumSizeForSplittin(){
		return this.minimumSizeForSplitting;
	}


}
